﻿using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
using System.Collections;
using Object = UnityEngine.Object;
using System.Collections.Generic;
#if UNITY_EDITOR
using UnityEditor;
#endif 


/// <summary>
/// -Helper script dependant on FrameFromDirection for each sprite it contains this will store 
/// a Vector2 hotspot which can then be retrieved at runtime.  So that bullets can be spawn from 
/// a guns barrel. 
/// The interface for this script is actually quite ‘neat’, crude in that it doesn’t use a proper 
/// inspector however it uses a hidden temporary and invisible game object aswell as locking 
/// the inspector so the hotspots can be positioned through the translation gizmo.  
/// Was quick to make and very easy to use.
/// To lock the inspector requires using reflection, beyond my knowledge but a nice and very useful  snippet was found.
/// http://forum.unity3d.com/threads/shortcut-key-for-lock-inspector.95815/
/// </summary>

[RequireComponent(typeof(FrameFromDirection))]
public class SpriteHotspot : MonoBehaviour {

    Transform Trnsfrm;
    FrameFromDirection FFD;

	void Start () {
	    Trnsfrm = transform;
        FFD = GetComponent<FrameFromDirection>();
	}
	
    public Vector2 getWP() {
        return Trnsfrm.TransformPoint(Hotspots[FFD.FrameI]);
	}

#if UNITY_EDITOR
    public bool Edit, Next;
    public int Frame = 0;
    int LFrame = -1;
    static GameObject Helper;
    static SpriteHotspot Active;

    //the following code is heavily 'inspired'...  http://forum.unity3d.com/threads/shortcut-key-for-lock-inspector.95815/
    private static EditorWindow _mouseOverWindow;
    static void setInspectorLock( bool val ) {
        if (_mouseOverWindow == null)  {
            if (!EditorPrefs.HasKey("LockableInspectorIndex"))
                EditorPrefs.SetInt("LockableInspectorIndex", 0);
            int i = EditorPrefs.GetInt("LockableInspectorIndex");
 
            Type type = Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.InspectorWindow");
            Object[] findObjectsOfTypeAll = Resources.FindObjectsOfTypeAll(type);
            _mouseOverWindow = (EditorWindow)findObjectsOfTypeAll[i];
        }
 
        if (_mouseOverWindow != null && _mouseOverWindow.GetType().Name == "InspectorWindow")  {
            Type type = Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.InspectorWindow");
            PropertyInfo propertyInfo = type.GetProperty("isLocked");
            bool value = (bool)propertyInfo.GetValue(_mouseOverWindow, null);
            if(value == val) return;
            propertyInfo.SetValue(_mouseOverWindow, val, null);
            _mouseOverWindow.Repaint();
        }
    }

    void OnDrawGizmos() {

        Trnsfrm = transform;
        FFD = GetComponent<FrameFromDirection>();

        if(FFD.Sprites.Count <= 0) return;

        if(Hotspots.Length != FFD.Sprites.Count) {
            var old = Hotspots;
            Hotspots = new Vector2[FFD.Sprites.Count];
            for(int i = Mathf.Min(old.Length, Hotspots.Length); i-- > 0; )
                Hotspots[i] = old[i];
        }

        if(Next) {
            if(++Frame >= Hotspots.Length) Frame = 0;
            Next = false;

        }
        Frame = Mathf.Clamp(Frame, 0, Hotspots.Length - 1);

        if(!Edit) {
            
            if(Active == this) {
                Active = null;
                setInspectorLock(false);
                if(Helper != null) {
                    if(Selection.activeObject == Helper)
                        Selection.activeObject = this;
                    DestroyImmediate(Helper);
                    Helper = null;
                }
            }
         
            if(Frame != LFrame) {
                LFrame = Frame;

                GetComponent<SpriteRenderer>().sprite = FFD.Sprites[Frame];
                SceneView.RepaintAll();
            } 
            return;
        }

        if(Active != this) {
            if(Active != null) Active.Edit = false;
            Active = this;
        }
        
        if(Helper == null) {
            Helper = GameObject.Find("_SpriteHotspot_HelperObject");
            if(Helper == null) {
                Helper = new GameObject();
                Helper.name = "_SpriteHotspot_HelperObject";
                Helper.transform.parent = Trnsfrm;
                Helper.transform.localPosition = Vector3.zero;
                Helper.hideFlags = HideFlags.HideInHierarchy;
                LFrame = -1;
            }
        }
       
        if(Frame != LFrame) {
            LFrame = Frame;
            Helper.transform.localPosition = Hotspots[Frame];

            GetComponent<SpriteRenderer>().sprite = FFD.Sprites[Frame];
            SceneView.RepaintAll();
        } else {
            Hotspots[Frame] = Helper.transform.localPosition;
            EditorUtility.SetDirty(this);
        }

        Selection.activeGameObject = gameObject;
        setInspectorLock(true);
        Selection.activeObject = Helper;
    }
#endif 

    public Vector2[] Hotspots = new Vector2[1]; 

}
